package cn.huijielong.common.utils;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.math.RandomUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.util.StringUtils;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import cn.huijielong.common.exception.VSException;
import net.sf.json.JSONObject;

public final class VSUtil {
	private static Logger logger = LoggerFactory.getLogger(VSUtil.class);
	
	
	public static Query requestFormToMap(HttpServletRequest request) {
		Map<String, String[]> params=request.getParameterMap();
		Query data=Query.empty();
		for(Map.Entry<String, String[]> entry:params.entrySet()) {
			String[] values=entry.getValue();
			if(values==null)
				continue;
			if(values.length==1)
				data.put(entry.getKey(), values[0]);
			else
				data.put(entry.getKey(), values);
		}
		return data;
	}
	/**
	 * 将request content中的json格式字符串转化为JSONObject
	 * @return
	 */
	public static Query requestToQuery() {
		return requestToQuery(false);
	}
	/**
	 * 将request content中的json格式字符串转化为JSONObject
	 * 
	 * @param request
	 * @return
	 */
	public static Query requestToQuery(boolean reset) {
		StringBuilder readStr=new StringBuilder();
		HttpServletRequest request=HttpContextUtils.getHttpServletRequest();
		String requestType=null;
		Query getQuery=Query.empty();
		try {
			String contentType=request.getHeader(HttpHeaders.CONTENT_TYPE);
			//获取URL上的参数
			String queryString=request.getQueryString();
			if(StringUtils.hasText(queryString)) {
				Query data = requestFormToMap(request);
				getQuery.putAll(data);
			}
			//application/x-www-form-urlencoded
			if(contentType==null) {
				if(StringUtils.hasText(queryString)) {
					logger.info("本次URL：{}，Content-type为空，返回GET请求参数：{}",request.getRequestURI(),queryString);
				}else {
					logger.warn("本次URL：{}，Content-type为空，不能获取参数值",request.getRequestURI());
				}
				return getQuery;
			}
			contentType=contentType.toLowerCase();
			//表单
			if(contentType.contains("form")) {
				Query data = requestFormToMap(request);
				getQuery.putAll(data);
				logger.info("本次URL：{}，请求(FORM)参数：{}",request.getRequestURI(),getQuery.toString());
				return getQuery;
			}
			if(contentType.contains("json")) {
				logger.info("传入数据格式为JSON，Content-type  =  {}",contentType);
				requestType="json";
			}else if(contentType.contains("xml")) {
				logger.info("传入数据格式为XML，Content-type  =  {}",contentType);
				requestType="xml";
			}else {
				logger.info("本次URL：{}，Content-type  =  {}，只返回GET请求参数{}",request.getRequestURI(),contentType,queryString);
				return getQuery;
			}
			InputStream inStream = request.getInputStream();
			if(reset)
				inStream.reset();
			List<String> list=org.apache.commons.io.IOUtils.readLines(inStream, request.getCharacterEncoding());
			org.apache.commons.io.IOUtils.closeQuietly(inStream);
			list.forEach(str->readStr.append(str));
			logger.info("本次URL：{}，请求参数：{}",request.getRequestURI(),readStr.toString());
		} catch (Exception e) {
			logger.error("本次请求出错，请求URL：{}，发送地址：{}",request.getRequestURI(),request.getHeader("referer"), e);
			return Query.empty();
		}
		
		
		if(readStr.length()==0){
			logger.debug("传入参数为空,参数不能解析为JSON：{}，发送地址：{}",request.getRequestURI(),request.getHeader("referer"));
			return Query.empty();
		}
		try {
			
			ObjectMapper mapper=getMapper(); 
			switch(requestType) {
			case "json":
				Map<String,Object> map=mapper.readValue(readStr.toString(),new TypeReference<Map<String,Object>>(){});
				getQuery.putAll(map);
				return getQuery;
			case "xml":
				Query q=xmlToQuery(readStr.toString());
				q.putAll(getQuery);
				return q;
			default:
				return Query.empty();
			}
		} catch (Exception e) {
			logger.error("JSON解析出错：{}，请求URL：{}，发送地址：{}",readStr.toString(),request.getRequestURI(),request.getHeader("referer"),e);
			return Query.empty();
		}
		
	}
	/**
	 * 将request content中的json格式字符串转化为JSONObject
	 * 
	 * @param request
	 * @return
	 */
	public static net.sf.json.JSONObject requestToJSON() {
		
		ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
		HttpServletRequest request=HttpContextUtils.getHttpServletRequest();
		try {
			String contentType=request.getHeader(HttpHeaders.CONTENT_TYPE);
			if(contentType==null || !contentType.toLowerCase().contains("json")) {
				logger.info("请求非JSON数据，Content-type  =  {}",contentType);
				return new net.sf.json.JSONObject();
			}
			InputStream inStream = request.getInputStream();
			byte[] buffer = new byte[1024];
			int len = -1;
			while ((len = inStream.read(buffer)) != -1) {
				outSteam.write(buffer, 0, len);
			}
			outSteam.close();
			inStream.close();
		} catch (Exception e) {
			logger.error("本次请求出错，请求URL：{}，发送地址：{}",request.getRequestURI(),request.getHeader("referer"), e);
			return new net.sf.json.JSONObject();
		}
		
		String jsonString = "";
		try {
			jsonString = new String(outSteam.toByteArray(),request.getCharacterEncoding());
			logger.info("本次URL：{}，请求参数：{}",request.getRequestURI(),jsonString);
		} catch (Exception e) {
			logger.error(new String(outSteam.toByteArray())+"，请求URL："+request.getRequestURI()+"，发送地址："+request.getHeader("referer"),e);
			return new net.sf.json.JSONObject();
		}
		if(jsonString==null ||  "".equals(jsonString)){
			logger.error("JSON解析出错",new VSException("传入参数为空,不能解析Json，请求URL："+request.getRequestURI())+"，发送地址："+request.getHeader("referer"));
			return new net.sf.json.JSONObject();
		}
		try {
			return net.sf.json.JSONObject.fromObject(jsonString);
		} catch (Exception e) {
			logger.error("JSON解析出错：{}，请求URL：{}，发送地址：{}",jsonString,request.getRequestURI(),request.getHeader("referer"),e);
			return new net.sf.json.JSONObject();
		}
		
	}
	
	public static ObjectMapper getMapper() {
		ObjectMapper mapper=new ObjectMapper();
		mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); 
		mapper.setSerializationInclusion(Include.NON_NULL);
		return mapper;
	}
	
	public static Query xmlToQuery(String xml){
		Query data=Query.empty();
		try {
			SAXReader reader = new SAXReader();  
	        Document document = reader.read(new java.io.StringReader(xml));
	        Element root = document.getRootElement();
	        List list=root.elements();
	        for(Object ele:list) {
	        	Element element=(Element)ele;
	        	data.put(element.getName(), element.getTextTrim());
	        }
		} catch (DocumentException e) {
			logger.error("",e);
		}
		return data;
	}
	
	public static <T> T stringToObject(String str,Class<T> valueType){
		try {
			return (T)getMapper().readValue(str, valueType);
		} catch (Exception e) {
			logger.error("转换对象出错："+str, e);
			return null;
		}
	}
	
	public static <T> T convertValue(Object fromValue,Class<T> valueType){
		if(fromValue==null)
			return null;
		try {
			return getMapper().convertValue(fromValue, valueType);
		} catch (Exception e) {
			logger.error("转换对象出错："+fromValue.toString(), e);
			return null;
		}
	}
	/**
	 * 返回定长位随机数
	 * @param len
	 * @return
	 */
	public static int getRandom(int len) {
		int max=(int) java.lang.Math.pow(10,len);
		int base=(int) java.lang.Math.pow(10,len-1);
		int r=RandomUtils.nextInt(max);
		if(r<base)
			r+=base;
		return r;
	}
	
	public static void main(String[] args) {
		
	}
	public static BigDecimal getDecimal(JSONObject json,String key) {
		if(json==null || !json.containsKey(key))
			return BigDecimal.ZERO;
		String v=json.optString(key,"0");
		try {
			return new BigDecimal(v).setScale(2, BigDecimal.ROUND_HALF_UP);
		}catch(Exception e) {
			logger.error(key+"对应的值为\""+v+"\"，不能转换成数字，返回0",e);
			return BigDecimal.ZERO;
		}
	}
	
	public static String getDayOfWeek(Date date){
		java.util.Calendar c=java.util.Calendar.getInstance();
    	Locale.setDefault(Locale.CHINESE);
    	c.setTime(date);
    	int d=c.get(java.util.Calendar.DAY_OF_WEEK);
    	d--;
    	switch(d){
    	case 1:
    		return "一";
    	case 2:
    		return "二";
    	case 3:
    		return "三";
    	case 4:
    		return "四";
    	case 5:
    		return "五";
    	case 6:
    		return "六";
    	case 0:
    		return "日";
    	default:
    		return "";
    	}
	}

}
